#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
using namespace std;
const int N=10;
void runchild()
{
    int cnt=5;
    for(int i=0;i<cnt;i++)
    {
        printf("I am child,pid:%d,ppid:%d,cnt:%d\n",getpid(),getppid(),cnt);
        sleep(1);
    }
}
#define TASK_NUM 10
typedef void (*task_t)();
task_t tasks[TASK_NUM];
void task1()
{
    cout<<"这是一个执行打印日志的任务,pid:"<<getpid()<<endl;
}

void task2()
{
    cout<<"这是一个检测网络健康状态的任务,pid:"<<getpid()<<endl;
}

void task3()
{
    cout<<"这是一个绘制图形界面的任务,pid:"<<getpid()<<endl;
}

void task4()
{
    cout<<"这是一个游戏的任务,pid:"<<getpid()<<endl;
}

//任务的管理代码
int AddTask(task_t t)
{
    int pos=0;   
    for(;pos<TASK_NUM;pos++)
    {
        if(!tasks[pos]) break;
    }
        if(pos==TASK_NUM) return -1;
        tasks[pos]=t;
        //添加成功
        return 0;
    
}

//执行逻辑
void ExecuteTask()
{
    for(int i=0;i<TASK_NUM;i++)
    {
        if(tasks[i])
        {
            tasks[i]();
        }
    }
}

void InitTask()
{
    for(int i=0;i<TASK_NUM;i++) tasks[i]=NULL;
}



int main()
{
    //同时wait多个进程
    /* for(int i=0;i<N;i++)
    {
        pid_t id=fork();
        if(id==0)
        {
            runchild();
            exit(i);
        }
        //只有父进程会执行
        printf("sccussfully create child,pid:%d\n",getpid());
    }
    sleep(10);
    //等待
    for(int i=0;i<N;i++)
    {
        //一次只能等待一个结果
       // pid_t id=wait(NULL);
       // -1表示等待任意一个进程
       int status=0;
        pid_t id=waitpid(-1,&status,0);
        if(id>0)
        {
            printf("wait %d success,exit code:%d\n",id,WEXITSTATUS(status));
            sleep(1);
        }
    
    }
    sleep(5);*/
 //单个子进程时，wait的使用
 
   pid_t id=fork();
   if(id<0)
   {
      perror("fork");//perror 会将该错误码翻译为人类可读的文本信息并打印
      return 1;
   }
   else if(id==0){
     int cnt=5;
    // int*p=NULL;
     //while(1) 无限循环逻辑(子进程不退出)可用 kill -9 观察现象
     while(cnt)
     {
         printf("I am child,pid:%d,ppid:%d,cnt:%d\n",getpid(),getppid(),cnt);
         cnt--;
         sleep(1);
          int a=10;
          //*p=10; 野指针错误示范
         // a/=0; 浮点数溢出示范
     }
     exit(10);
   }
   else{
      // int cnt=10;
      // while(cnt--)
      // {
      //      printf("I am father,pid:%d,ppid:%d,cnt:%d\n",getpid(),getppid(),cnt);
      //      sleep(1);
      // }
       //与wait(NULL)作用是相似的
      int status=0;
      //等待子进程
      // pid_t ret=waitpid(id,&status,0); 采用默认的阻塞等待，只有子进程终止时才返回
      // if(ret==id)
      InitTask();
      AddTask(task1);
      AddTask(task2);
      AddTask(task3);
      AddTask(task4);
      while(1) 
      {
         pid_t ret=waitpid(id,&status,WNOHANG);
         if(ret>0) //子进程终止
         {
               //7F:0111 1111 0xFF:1111 1111 按位与可以得到 退出信号和退出码
             // printf("wait success,ret:%d,exit sig:%d,exit code:%d\n",ret,status&0x7F,(status>>8)&0xFF);
             //实际上，系统提供了调用接口
             if(WIFEXITED(status))
             {
               printf("进程正常运行完毕，退出码:%d\n",WEXITSTATUS(status));
              }
             else{
                   //子进程异常
                 cout<<"进程异常"<<endl;
             }
             break;
         }
        else  if(ret<0)
         {
              printf("wait failed\n");
              break;
              //无论是子进程异常还是正常返回，直接break
         }
         else 
         {
            printf("子进程仍在运行,继续等待\n");
            ExecuteTask();
            usleep(100000);
            // sleep(1);
         }
     }
     // sleep(3);
   }
    return 0;
}
